/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Module Name          : com.yaodian100.ec.campaign.entity.Campaign
   Module Description   :

   Date Created      : 2009/11/18
   Original Author   : eric.chen
   Team              : yaodian100
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   MODIFICATION HISTORY
   ------------------------------------------------------------------------------
   Date Modified       Modified by       Comments
   ------------------------------------------------------------------------------
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
package com.yaodian100.ec.campaign.entity;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import org.json.JSONException;
import org.json.JSONObject;

import com.yaodian100.core.common.entity.BaseEntity;

/**
 * @author eric.chen
 * 
 *         This Entity record the campaign settings on EC
 * 
 */
@Entity
@Table(name = "EC_CAMPAIGN_MAIN")
public class Campaign extends BaseEntity {

	/* serialVersionUID */
	private static final long serialVersionUID = -3808543152438398055L;

	public enum Type {
		// 滿足條件, 則滿足條件的商品立即折抵 amount*(100-X)/100 元, X 設定於 typeExtends.campaignTypeExtension, 且小於 100
		C01("立折优惠"),
		// 滿足條件, 則立即折抵 X 元, X 設定於 typeExtends.campaignTypeExtension
		C02("立减优惠"),
		// 滿足條件, 則購物車新增一贈品, 售價為 0 元. 需計算運費, 使用者不可取消.
		C03("活动赠品"),
		// 滿足條件, 則於退貨期限後送 购物金, 购物金金額 維護於 typeExtends.campaignTypeExtension
		S01("购物金"),
		// 滿足條件, 則於退貨期限後送 折价券(coupon), coupon 維護於 typeExtends.campaignTypeExtension
		S02("折价券"),
		// 於活動結束後, 隨機選取列表
		// S03("抽奖");
		M01("会员积分发送"),
		// 发放基准及换算值（按比例／固定值）,效期开始日（为发放日之N日后开始可用）,效期时幅（效期起算日 + M日）
		M02("会员积分折抵"),
		// 折抵比率（X 点购物金 -> 1 元）,折抵上限（％）
		M03("会员登录发送积分活动"),
		// 发送规则（会员每日登录 X 次(含)，发送积分 Y 点）
		M04("评价送积分");
		// 发送规则（商品评价前三名送 X点, 其馀送 Y点）
		String desc;

		Type(String desc) {
			this.desc = desc;
		}

		public String getDesc() {
			return desc;
		}

		public String getCode() {
			return name();
		}
	}

	public enum Range {
		// 整張訂單生效
		Order("全站"),
		// 以"," 分隔活動目錄, 以加入購物車的 z 為準.
		Category("分類"),
		// 活動商品代碼. 限放一個
		Product("商品"),
		// 紅配綠的商品分類,以","分隔
		RedGreenCategory("红绿配分类");
		String desc;

		Range(String desc) {
			this.desc = desc;
		}

		public String getDesc() {
			return desc;
		}

		public String getCode() {
			return name();
		}
	}

	@Id
	@GeneratedValue(generator = "gen_uuid")
	@GenericGenerator(name = "gen_uuid", strategy = "uuid")
	@Column(name = "OBJ_UUID")
	private String uuid;

	/**
	 * 活动名称 Campaign Name
	 */
	@Column(name = "CAMPAIGN_NAME", length = 100, nullable = false)
	private String campaignName;

	/**
	 * 活动说明 Campaign Description
	 */
	@Column(name = "CAMPAIGN_DESCRIPTION", length = 500)
	private String campaignDesc;

	/**
	 * 活动辦法 Campaign Detail
	 */
	@Column(name = "CAMPAIGN_DETAIL", length = 1000)
	private String campaignDetail;
	/**
	 * 红色标签分类
	 */
	@Column(name = "RED_RANGE", length = 1000)
	private String redRange;
	/**
	 * 绿色标签分类
	 */
	@Column(name = "GREEN_RANGE", length = 1000)
	private String greenRange;
	/**
	 * 活动类型 Campaign Type
	 */
	@Enumerated(EnumType.STRING)
	@Column(name = "CAMPAIGN_TYPE", length = 4, nullable = false)
	private Type type = Type.C01;
	/** typeExtends, 因為 rangeExtList joinTable, fetch 請勿設 FetchType.EAGER */
	@OneToMany(targetEntity = CampaignExtend.class, mappedBy = "campaign", fetch = FetchType.LAZY)
	@Cascade( { CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN })
	@OnDelete(action = OnDeleteAction.CASCADE)
	@OrderBy("minOrderAmount asc, minQty asc")
	private List<CampaignExtend> typeExtends;

	/** range, 活动范围 */
	@Column(name = "CAMPAIGN_RANGE", columnDefinition = "numeric(2)", nullable = false)
	private Range range = Range.Order;
	@XmlTransient
	@CollectionOfElements(targetElement = String.class, fetch = FetchType.EAGER)
	@JoinTable(name = "EC_CAMPAIGN_RANGE", joinColumns = @JoinColumn(name = "OBJ_UUID", referencedColumnName = "OBJ_UUID"))
	@Column(name = "RANGE_EXT", length = 30)
	private Set<String> rangeExtList;

	/**
	 * 活动开始时间 Start Date
	 */
	@Column(name = "START_DATE_TIME", nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date startDateTime;

	/**
	 * 活动结束时间 End Date
	 */
	@Column(name = "END_DATE_TIME", nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date endDateTime;

	/** campaignUrl, 放置活動公告靜態網頁 */
	@Column(name = "URL", length = 200)
	private String campaignUrl;

	/** cookie, 若該欄位有值, 則結帳時, 必須要有該 cookie 值, 才符合活動要求 */
	@Column(name = "COOKIE", length = 100)
	private String cookie = null;
	/** domain */
	@Column(name = "DOMAIN", length = 100, nullable = false)
	private String domain = "www.yaodian100.com";
	/** checkScript, 其他活動判斷 script */
	@Column(name = "SCRIPT", length = 800)
	private String checkScript;

	/**
	 * 该活动是否启用, Y: 是； N: 否
	 */
	@Column(name = "IS_ENABLE", nullable = false)
	private boolean enable = false;

	/**
	 * 备注栏位
	 */
	@Column(name = "MEMO", length = 1000)
	private String memo;

	/**
	 * 删除标记 , Y: 是； N: 否
	 */
	@Column(name = "IS_DELETE", nullable = false)
	private boolean delete = false;

	/** budget, 预算归属, 維護於選單 Menu 'Budget' */
	@Column(name = "BUDGET", length = 2)
	private String budget = "A";

	/**
	 * 积分资料(积分发送、积分折抵、会员登入发送积分规则)
	 */
	@Column(name = "JSON_DETAIL", length = 200)
	private String jsonDetail;

	/**
	 * 效期開始日
	 */
	@Transient
	private String startPeriod;

	/**
	 * 效期長度, 以月份为单位
	 */
	@Transient
	private String periodDays;

	/**
	 * 折抵比率
	 */
	@Transient
	private String offsetRate;

	/**
	 * 折抵上限
	 */
	@Transient
	private String offsetUpperLimit;

	/**
	 * 订单折抵上限金额
	 */
	@Transient
	private String offsetDiscountLimit;

	/**
	 * 登入次數
	 */
	@Transient
	private String loginCount;

	/**
	 * 發送點數
	 */
	@Transient
	private String giveBonus;

	/**
	 * 商品评价前三名发送积分
	 */
	@Transient
	private String commentFirst3;

	/**
	 * 商品评价第四名以后发送积分
	 */
	@Transient
	private String commentOthers;

	/**
	 * 會員等級
	 */
	@Column(name = "ALLOW_MEMBER_RANK", length = 1)
	private String rank;

	/** default constructor */
	public Campaign() {
	}

	/**
	 * @return the budget
	 */
	public String getBudget() {
		return budget;
	}

	/**
	 * @param budget the budget to set
	 */
	public void setBudget(String budget) {
		this.budget = budget;
	}

	/**
	 * @return the uuid
	 */
	public String getUuid() {
		return uuid;
	}

	/**
	 * @param uuid the uuid to set
	 */
	public void setUuid(String uuid) {
		this.uuid = uuid;
	}

	/**
	 * @return the campaignName
	 */
	public String getCampaignName() {
		return campaignName;
	}

	/**
	 * @param campaignName the campaignName to set
	 */
	public void setCampaignName(String campaignName) {
		this.campaignName = campaignName;
	}

	/**
	 * @return the campaignDesc
	 */
	public String getCampaignDesc() {
		return campaignDesc;
	}

	/**
	 * @param campaignDesc the campaignDesc to set
	 */
	public void setCampaignDesc(String campaignDesc) {
		this.campaignDesc = campaignDesc;
	}

	/**
	 * @return the type
	 */
	public Type getType() {
		return type;
	}

	/**
	 * @param type the type to set
	 */
	public void setType(Type type) {
		this.type = type;
	}

	/**
	 * @return the startDateTime
	 */
	public Date getStartDateTime() {
		return startDateTime;
	}

	/**
	 * @param startDateTime the startDateTime to set
	 */
	public void setStartDateTime(Date startDateTime) {
		this.startDateTime = startDateTime;
	}

	/**
	 * @return the endDateTime
	 */
	public Date getEndDateTime() {
		return endDateTime;
	}

	/**
	 * @param endDateTime the endDateTime to set
	 */
	public void setEndDateTime(Date endDateTime) {
		this.endDateTime = endDateTime;
	}

	/**
	 * @return the enable
	 */
	public boolean isEnable() {
		return enable;
	}

	/**
	 * @param enable the enable to set
	 */
	public void setEnable(boolean enable) {
		this.enable = enable;
	}

	/**
	 * @return the memo
	 */
	public String getMemo() {
		return memo;
	}

	/**
	 * @param memo the memo to set
	 */
	public void setMemo(String memo) {
		this.memo = memo;
	}

	/**
	 * @return the delete
	 */
	public boolean isDelete() {
		return delete;
	}

	/**
	 * @param delete the delete to set
	 */
	public void setDelete(boolean delete) {
		this.delete = delete;
	}

	/**
	 * @return the range
	 */
	public Range getRange() {
		return range;
	}

	/**
	 * @param range the range to set
	 */
	public void setRange(Range range) {
		this.range = range;
	}

	/**
	 * @return the rangeExt
	 */
	@Transient
	public String getRangeExt() {
		return StringUtils.join(getRangeExtList(), ",");
	}

	@XmlTransient
	@Transient
	public List<String> getRangeExtIds() {
		List<String> ids = new ArrayList<String>();
		if (Range.Product.equals(range)) {
			ids.addAll(getRangeExtList());
		} else if (Range.Category.equals(range)) {
			for (String s : getRangeExtList()) {
				String[] c = StringUtils.split(s, "/");
				ids.add(c[c.length - 1]);
			}
		}
		return ids;
	}

	/**
	 * @return the rangeExt
	 */
	public Set<String> getRangeExtList() {
		if (rangeExtList == null) {
			rangeExtList = new HashSet<String>();
		}
		return rangeExtList;
	}

	/**
	 * @param rangeExtList the rangeExtList to set
	 */
	public void setRangeExtList(Set<String> rangeExtList) {
		this.rangeExtList = rangeExtList;
	}

	/**
	 * @return the campaignUrl
	 */
	public String getCampaignUrl() {
		return campaignUrl;
	}

	/**
	 * @param campaignUrl the campaignUrl to set
	 */
	public void setCampaignUrl(String campaignUrl) {
		this.campaignUrl = campaignUrl;
	}

	/**
	 * @return the cookie
	 */
	public String getCookie() {
		return cookie;
	}

	@XmlTransient
	@Transient
	public List<String> getCookieArray() {
		List<String> cookieArray = new ArrayList();
		if (StringUtils.isNotBlank(cookie)) {
			for (String s : StringUtils.split(cookie, ",")) {
				cookieArray.add(s);
			}
		}
		return cookieArray;
	}

	public void setCookieArray(List<String> cookieArray) {
		if (cookieArray != null) {
			cookie = StringUtils.join(cookieArray, ",");
		}
	}

	/**
	 * @param cookie the cookie to set
	 */
	public void setCookie(String cookie) {
		this.cookie = cookie;
	}

	/**
	 * @return the checkScript
	 */
	public String getCheckScript() {
		return checkScript;
	}

	/**
	 * @param checkScript the checkScript to set
	 */
	public void setCheckScript(String checkScript) {
		this.checkScript = checkScript;
	}

	/**
	 * @return the typeExtends
	 */
	public List<CampaignExtend> getTypeExtends() {
		if (typeExtends == null) {
			typeExtends = new ArrayList<CampaignExtend>();
		}
		return typeExtends;
	}

	/**
	 * @param typeExtends the typeExtends to set
	 */
	public void setTypeExtends(List<CampaignExtend> typeExtends) {
		this.typeExtends = typeExtends;
	}

	public Campaign addTypeExtend(int index, CampaignExtend ext) {
		ext.setCampaign(this);
		getTypeExtends().add(index, ext);
		return this;
	}

	public Campaign addTypeExtend(CampaignExtend ext) {
		ext.setCampaign(this);
		getTypeExtends().add(ext);
		return this;
	}

	/**
	 * @return the campaignDetail
	 */
	public String getCampaignDetail() {
		return campaignDetail;
	}

	/**
	 * @param campaignDetail the campaignDetail to set
	 */
	public void setCampaignDetail(String campaignDetail) {
		this.campaignDetail = campaignDetail;
	}

	/**
	 * @return the Domain
	 */
	public String getDomain() {
		return domain;
	}

	/**
	 * @param Domains the Domains to set
	 */
	public void setDomain(String domain) {
		this.domain = domain;
	}

	public String getRedRange() {
		return redRange;
	}

	public void setRedRange(String redRange) {
		this.redRange = redRange;
	}

	public String getGreenRange() {
		return greenRange;
	}

	public void setGreenRange(String greenRange) {
		this.greenRange = greenRange;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Campaign [uuid=" + uuid + ", campaignName=" + campaignName + ", enable=" + enable + ", range=" + range
				+ ", type=" + type + ", domains=" + domain + "]";
	}

	public String getJsonDetail() {
		try {
			if (StringUtils.isNotBlank(jsonDetail)) {
				JSONObject jsonObj = new JSONObject(jsonDetail);
				if (null != jsonObj) {
					if (type.getCode().equals(Type.M01.getCode())) {// 积分发送
						if (StringUtils.isBlank(startPeriod)) {
							setStartPeriod(jsonObj.getString("startPeriod"));// 效期開始日
						}
						if (StringUtils.isBlank(periodDays)) {
							setPeriodDays(jsonObj.getString("periodDays"));// 效期長度
						}
					}
					if (type.getCode().equals(Type.M02.getCode())) {// 积分折抵
						if (StringUtils.isBlank(offsetRate)) {
							setOffsetRate(jsonObj.getString("offsetRate"));// 折抵比率
						}
						if (StringUtils.isBlank(offsetUpperLimit)) {
							setOffsetUpperLimit(jsonObj.getString("offsetUpperLimit"));// 折抵上限
						}
						if (StringUtils.isBlank(offsetDiscountLimit)) {
							setOffsetDiscountLimit(jsonObj.getString("offsetDiscountLimit"));// 折抵上限金额
						}
					}
					if (type.getCode().equals(Type.M03.getCode())) {// 会员登入积分发送
						if (StringUtils.isBlank(loginCount)) {
							setLoginCount(jsonObj.getString("loginCount"));// 登入次數
						}
						if (StringUtils.isBlank(giveBonus)) {
							setGiveBonus(jsonObj.getString("giveBonus"));// 發送點數
						}
					}
					if (type.getCode().equals(Type.M04.getCode())) {// 商品评价积分发送
						if (StringUtils.isBlank(commentFirst3)) {
							setCommentFirst3(jsonObj.getString("commentFirst3"));// 前三名
						}
						if (StringUtils.isBlank(commentOthers)) {
							setCommentOthers(jsonObj.getString("commentOthers"));// 第四名以后
						}
						if (StringUtils.isBlank(startPeriod)) {
							setStartPeriod(jsonObj.getString("startPeriod"));// 效期開始日
						}
						if (StringUtils.isBlank(periodDays)) {
							setPeriodDays(jsonObj.getString("periodDays"));// 效期長度
						}
					}
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return jsonDetail;
	}

	public void setJsonDetail(String jsonDetail) {
		this.jsonDetail = jsonDetail;
	}

	public String getStartPeriod() {
		getJsonDetail();
		return startPeriod;
	}

	public String getPeriodDays() {
		getJsonDetail();
		return periodDays;
	}

	public String getLoginCount() {
		getJsonDetail();
		return loginCount;
	}

	public String getGiveBonus() {
		getJsonDetail();
		return giveBonus;
	}

	public void setStartPeriod(String startPeriod) {
		this.startPeriod = startPeriod;
	}

	public void setPeriodDays(String periodDays) {
		this.periodDays = periodDays;
	}

	public void setLoginCount(String loginCount) {
		this.loginCount = loginCount;
	}

	public void setGiveBonus(String giveBonus) {
		this.giveBonus = giveBonus;
	}

	public String getOffsetRate() {
		getJsonDetail();
		return offsetRate;
	}

	public void setOffsetRate(String offsetRate) {
		this.offsetRate = offsetRate;
	}

	public String getRank() {
		return rank;
	}

	public void setRank(String rank) {
		this.rank = rank;
	}

	public String getOffsetUpperLimit() {
		getJsonDetail();
		return offsetUpperLimit;
	}

	public void setOffsetUpperLimit(String offsetUpperLimit) {
		this.offsetUpperLimit = offsetUpperLimit;
	}

	public String getOffsetDiscountLimit() {
		getJsonDetail();
		return offsetDiscountLimit;
	}

	public void setOffsetDiscountLimit(String offsetDiscountLimit) {
		this.offsetDiscountLimit = offsetDiscountLimit;
	}

	public String getCommentFirst3() {
		getJsonDetail();
		return commentFirst3;
	}

	public void setCommentFirst3(String commentFirst3) {
		this.commentFirst3 = commentFirst3;
	}

	public String getCommentOthers() {
		getJsonDetail();
		return commentOthers;
	}

	public void setCommentOthers(String commentOthers) {
		this.commentOthers = commentOthers;
	}
}